//
//  GlViewController.swift
//  flutter_test_opengl_plugin
//
//  Created by yuanxc on 2024/5/24.
//

import Foundation
import GLKit
import OpenGLES

class GlViewController: GLKViewController {
    var context: EAGLContext?
    var esContext: ESContext!
    var glkView: GLKView?

    var getView: GLKView? {
        glkView
    }

    deinit {
        guard EAGLContext.current() == self.context else {
            return
        }
        EAGLContext.setCurrent(nil)
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

        context = EAGLContext.init(api: .openGLES3)
        guard let context = context else {
            print("Failed to create es context")
            return
        }

        self.delegate = self

        let newView = self.view as? GLKView
        newView?.context = context
        newView?.drawableDepthFormat = .format24
        glkView = newView
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setupGL()
    }

    func tearDownGL() {
        EAGLContext.setCurrent(self.context)
        if esContext.shutdownFunc != nil {
            esContext.shutdownFunc(&esContext)
        }
    }

    func setupGL() {
        EAGLContext.setCurrent(self.context)
        memset(&esContext, 0, MemoryLayout.size(ofValue: esContext))
        esContext.width = GLint(self.view.frame.width);
        esContext.height = GLint(self.view.frame.height);
        esMain(&esContext);
    }

    func update() {
        guard esContext.updateFunc != nil else {
            return
        }
        esContext.updateFunc(&esContext, Float(self.timeSinceLastUpdate))
    }

    override func glkView(_ view: GLKView, drawIn rect: CGRect) {
        esContext.width = GLint(view.drawableWidth)
        esContext.height = GLint(view.drawableHeight)

        guard esContext.drawFunc != nil else {
            return
        }
        esContext.drawFunc(&esContext)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        if self.isViewLoaded && self.view.window == nil {
            self.view = nil

            tearDownGL()

            if EAGLContext.current() == self.context {
                EAGLContext.setCurrent(nil)
            }
            self.context = nil
        }
    }
}

extension GlViewController: GLKViewControllerDelegate {
    func glkViewControllerUpdate(_ controller: GLKViewController) {
        update()
    }
}
